package com.aggregate.pay.quanzi.support;

import java.net.SocketTimeoutException;
import java.util.Map;

import com.aggregate.pay.quanzi.bean.AbstractData;
import com.aggregate.pay.quanzi.bean.AbstractResult;
import com.aggregate.pay.quanzi.support.utils.JSON;

/**
 * 接口API操作类抽象类
 * @author Moyq5
 * @date 2017年9月29日
 * @param <D>
 * @param <R>
 */
public abstract class AbstractClient<D extends AbstractData, R extends AbstractResult> implements Client<D, R> {
		
	private Merch merch;
	
	public AbstractClient(Merch merch) {
		this.merch = merch;
	}
	
	@Override
	public R execute(D data) {
		R resResult = null;
		try {
			data.setMerNo(merch.merchNo());
			//data.setOrderDate(new SimpleDateFormat("yyyyMMdd").format(new Date()));
			data.setRequestNo(data.getOrderDate() + (long)(Math.random() * Long.MAX_VALUE));
			data.setVersion("V1.0");
			
			HttpClient client = Factory.getHttpClient();
			Map<String, String> params = getReqParams(data);
			String resBody = client.post(Factory.getConfig().getServerPath(), params);
			resResult = JSON.toObject(resBody, resultClass());
			if (resResult.getRespCode().equals("0000") && !verifySign(resBody)) {
				resResult = resultClass().newInstance();
				resResult.setRespCode("C9999");
				resResult.setRespDesc("签名有误");
				return resResult;
			}
			return resResult;
			
		} catch (SocketTimeoutException e) {
			try {
				resResult = resultClass().newInstance();
			} catch (Exception e1) {
				e1.printStackTrace();
			}
			resResult.setRespCode("C9999");
			resResult.setRespDesc("请求超时");
		} catch (Exception e) {
			log.error("接口调用失败", e);
			try {
				resResult = resultClass().newInstance();
			} catch (Exception e1) {
				e1.printStackTrace();
			}
			resResult.setRespCode("C9999");
			resResult.setRespDesc("本地错误：" + e.getMessage());
		}
		return resResult;
	}
	
	private Map<String, String> getReqParams(D data) throws Exception {
		return Tool.sign(data, merch.privateKey());
	}
	
	private boolean verifySign(String data) throws Exception {
		return Tool.verify(data, merch.publicKey());
	}
	
	protected abstract Class<R> resultClass();
	
}
